#pragma once
#include <string>
#include <iostream>
#include <vector>
#include "test_result.h"

namespace krryn{
namespace test{
	class result;
	class basic_report{
	public:
		virtual ~basic_report() {}

		virtual void test_begin(size_t a_Nr, const std::string &a_Name = "") {}
		virtual void test_end(size_t a_Nr, const result &a_Result, const std::string &a_Name = "") {}

		virtual void suite_begin(const std::string &a_Name) {}
		virtual void suite_end(const std::string &a_Name, size_t a_MaxTests) {}

		virtual void begin(size_t a_MaxTotal) {}
		virtual void end() {}
	};

	/**
	 * Swallow all output.
	 */
	class report_null : public basic_report{};

	/**
	 * The composite class allows output to two reports, combine composites to
	 * allow for more than two reports to be generated.
	 */
	class report_composite : public basic_report{
	public:
		report_composite(basic_report *a_First, basic_report *a_Second);
		virtual ~report_composite();

		virtual void test_begin(size_t a_Nr, const std::string &a_Name);
		virtual void test_end(size_t a_Nr, const result &a_Result, const std::string &a_Name);
		virtual void suite_begin(const std::string &a_Name);
		virtual void suite_end(const std::string &a_Name, size_t a_MaxTests);
		virtual void begin(size_t a_MaxTotal);
		virtual void end();
	private:
		basic_report *m_First;
		basic_report *m_Second;
	};

	/**
	 * Simple report generated to a std::ostream, default output is to std::cout
	 */
	class report_stream : public basic_report{
	public:
		report_stream();
		report_stream(std::ostream &a_Output);

		virtual void test_end(size_t a_Nr, const result &a_Result, const std::string &a_Name);
		virtual void end();
	private:
		typedef std::vector<result> result_list_t;
		std::ostream &m_Output;
		result_list_t m_Results;
	};
}
}